package com.yanqu.road.server.manager.activity.daomu.pvp;

import com.google.protobuf.AbstractMessage;
import com.yanqu.road.entity.activity.daomu.config.DaoMuActivityConfig;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.kuang.Kuang;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.entity.activity.daomu.pvp.Coordinate;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.AgentProtocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class DaoMuActivityPvpBase {

    public DaoMuActivityPvpBase(DaoMuActivityConfig config) {
        this.config = config;
    }

    protected static Logger logger = LogManager.getLogger(DaoMuActivityPvpBase.class.getName());

    /**
     * 大锁
     */
    protected final Object lock = new Object();

    protected static RandomHelper randomHelper = new RandomHelper();

    //活动配置信息
    protected DaoMuActivityConfig config;


    /**
     * pvp死亡掉落经验点
     */
    protected int PVP_DROP_EXP_ID = 100;

    /**
     * pvp死亡掉落武器
     */
    protected int PVP_DROP_BULLET_ID = 200;

    /**
     * 原点坐标
     */
    protected Coordinate ZERO_COORDINATE = new Coordinate(0, 0);



    public DaoMuActivityConfig getConfig() {
        return config;
    }

    protected void sendPacket(int code, AbstractMessage.Builder<?> messageBuilder, long userId) {
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo == null) {
            return;
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(code, messageBuilder);
        MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, message);
    }

    protected void sendPacketToAll(int code, AbstractMessage.Builder<?> messageBuilde, Collection<Long> userIdList) {
        if (userIdList == null || userIdList.isEmpty()) {
            return;
        }
        Kuang.KuangAgentTransferMsg.Builder agentMsg = Kuang.KuangAgentTransferMsg.newBuilder();
        agentMsg.setCode(code);
        agentMsg.addAllUserId(userIdList);
        agentMsg.setMsg(messageBuilde.build().toByteString());
        Set<Long> serverIdList = new HashSet<>();
        for (Long userId : userIdList) {
            serverIdList.add(CrossUserMgr.getServerIdByUserId(userId));
        }
        YanQuMessage message = YanQuMessageUtils.buildMessage(AgentProtocol.A_DAOMU_TRANSFER, agentMsg);
        // 获取下分组的服务器列表
        for (Long serverId : serverIdList) {
            MessageHelper.sendPacket(serverId, 0, message);
        }
    }

    public void reloadConfig(DaoMuActivityConfig config) {
        this.config = config;
    }

    /**
     * 获取大于等于给定值的最小的2的n次方的值，其中n为偶数。
     */
    protected static int nextPowerOfTwo(int value) {
        int n = 0;
        while ((1 << n) < value || n % 2 != 0) {
            n++;
        }
        return 1 << n;
    }

    /**
     * 获取大于等于给定值的最小的n的2次方的值
     */
    protected static int getNextSquare(int value) {
        int n = 0;
        while (Math.pow(n, 2) < value) {
            n++;
        }
        return (int) Math.pow(n, 2);
    }

    protected static String randomUUID(){
        return UUIDHelper.randomUUID("dm");
    }

    /**
     * 获取圆内随机一点的坐标
     *
     * @param x x轴
     * @param y y轴
     * @param r 半径
     */
    protected static Coordinate generateRandomCoordinate(double x, double y, double r) {
        double angle = Math.toRadians(randomHelper.next(0, 360));
        double radius = r * Math.sqrt(randomHelper.nextDouble(0, 1));
        return new Coordinate(x + radius * Math.cos(angle), y + radius * Math.sin(angle));
    }

    /**
     * 判断两点的距离
     */
    protected double distance(Coordinate coordinate1, Coordinate coordinate2) {
        return Math.sqrt(Math.pow(coordinate2.getX() - coordinate1.getX(), 2) + Math.pow(coordinate2.getY() - coordinate1.getY(), 2));
    }

    /**
     * 计算方向向量
     * @param coordinate1   原
     * @param coordinate2   目标
     * @return
     */
    protected Coordinate calcDirection(Coordinate coordinate1, Coordinate coordinate2) {
        double dx = coordinate2.getX() - coordinate1.getX();
        double dy = coordinate2.getY() - coordinate1.getY();

        // 归一化处理
        double mag = Math.sqrt(dx * dx + dy * dy);
        return new Coordinate(dx / mag, dy / mag);
    }

    /**
     * 是否在报名期
     */
    protected boolean isApplyTime() {
        long nowTime = System.currentTimeMillis();
        long zeroTimeStamp = DateHelper.getTodayZeroTimeStamp();
        long startTimeStamp = zeroTimeStamp + config.getPvpCommonConfig().getEnterNameStartTime() * DateHelper.SECOND_MILLIONS;
        long endTimeStamp = zeroTimeStamp + config.getPvpCommonConfig().getEnterNameEndTime() * DateHelper.SECOND_MILLIONS;
        return nowTime >= startTimeStamp && nowTime <= endTimeStamp;
    }

    /**
     * 是否在战斗期
     */
    protected boolean isBattleTime() {
        long nowTime = System.currentTimeMillis();
        return nowTime >= getBattleStartTime() && nowTime <= getBattleEndTime();
    }

    /**
     * 战斗期含准备期前5分钟(生成数据用)
     */
    protected boolean isPreBattleTime() {
        long nowTime = System.currentTimeMillis();
        return nowTime >= getBattleStartTime() - 5 * DateHelper.MINUTE_MILLIONS && nowTime <= getBattleEndTime();
    }

    protected long getBattleStartTime() {
        long zeroTimeStamp = DateHelper.getTodayZeroTimeStamp();
        return zeroTimeStamp + config.getPvpCommonConfig().getPvpContinuedStartTime() * DateHelper.SECOND_MILLIONS;
    }

    protected long getBattleEndTime() {
        long zeroTimeStamp = DateHelper.getTodayZeroTimeStamp();
        return zeroTimeStamp + config.getPvpCommonConfig().getPvpContinuedEndTime() * DateHelper.SECOND_MILLIONS;
    }

    public static void main(String[] args) {
        System.out.println(getNextSquare(15));
        System.out.println(getNextSquare(16));
        System.out.println(getNextSquare(17));
    }
}
